#include <process.h>	// thread handles
#include "Block.h"

// Constructor
Block::Block(char *index, int size) {
	// default link list values
	this->prev = this->next = NULL;

	// store index & size
	this->index = _strdup(index);
	this->size = size;

	// initialize temporary index store
	this->sindex = NULL;

	// initialize the status of each todo
	this->handles = new HANDLE[this->size];
	this->status = new char[this->size];

	// initial values of status counts
	this->counts[0] = this->size;
	this->counts[1] = 0;
	this->counts[2] = 0;

	// status value is null until a thread has been added
	for(int loop = 0; loop < this->size; loop ++) {
		this->status[loop] = 0;
		this->handles[loop] = NULL;
	}
}

// Deconstructor
Block::~Block() {
	if(this->sindex) {
		OPENSSL_free(this->sindex);
	}
	delete[] this->status;

	// close each of the thread handles
	for(int loop = 0; loop < this->size; loop ++) {
		CloseHandle(this->handles[loop]);
	}
	delete[] this->handles;

	free(this->index);
}


// returns total number of todos in 'pending' state
int Block::getPending() {
	return this->counts[0];
}

// returns total number of todos in 'active' state
int Block::getActive() {
	return this->counts[1];
}

// returns total number of todos in 'complete' state
int Block::getComplete() {
	return this->counts[2];
}

// whether block is complete
bool Block::isComplete() {
	// update status counts
//	this->update();

	// return if all todos are complete
	if(this->getComplete() == this->size) {
		return true;
	}

	return false;
}

// returns the next index to start
char* Block::getNextIndex() {
	for(int loop = 0; loop < this->size; loop ++) {
		// first check if a thread is being tracked
		if(status[loop] == NULL) {
			BIGNUM *tmp = BN_new();
			BN_dec2bn(&(tmp), this->index);
			BN_add_word(tmp, loop);
			if(this->sindex) {
				OPENSSL_free(this->sindex);
			}
			this->sindex = BN_bn2dec(tmp);
			BN_free(tmp);
			return this->sindex;
		}
	}

	return NULL;
}

/*
// track the todo thread
int Block::track_start(HANDLE todo) {
	for(int loop = 0; loop < this->size; loop ++) {
		// first check if a thread is being tracked
		if(status[loop] == 0) {
			status[loop] = 1;
			handles[loop] = todo;
			return loop;
		}
	}

	return -1;
}
*/

// track the todo thread
bool Block::track_end(int index) {
	// blindly trust the index parameter to be a completed thread
	status[index] = 2;
//	CloseHandle(this->handles[index]);

	// adjust counts
	-- this->counts[1];		// one less active
	++ this->counts[2];		// one more complete

	return true;
}